<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>我的AI助手</title>
    <link rel="stylesheet" th:href="@{/webjars/bootstrap/5.3.3/css/bootstrap.min.css}">
    <script th:src="@{/webjars/popper.js/2.9.3/umd/popper.min.js}"></script>
    <script th:src="@{/webjars/jquery/3.5.1/jquery.min.js}"></script>
    <script th:src="@{/js/marked.min.js}"></script>
    <style>
        .user-message {
            background-color: #d4edda;
            padding: 10px;
            border-radius: 5px;
            margin-bottom: 10px;
        }
        .bot-message {
            background-color: #d1ecf1;
            padding: 10px;
            border-radius: 5px;
            margin-bottom: 10px;
        }
        .message-group {
            margin-bottom: 20px;
        }
        .icon {
            width: 20px;
            height: 20px;
            margin-right: 5px;
        }
        .chat-container {
            display: flex;
            flex-direction: column;
            height: 100vh;
        }
        .chat-window {
            #flex: 1;
            overflow-y: auto;
            height: calc(100vh - 400px); /* Adjust this value as needed */
        }
        .table-container {
            overflow-x: auto;
        }
        table {
            width: 100%;
            table-layout: fixed;
        }
        th, td {
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        th:hover, td:hover {
            overflow: visible;
            white-space: normal;
        }
        .form-row {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .form-row .btn-group {
            display: flex;
            gap: 10px;
        }
        th.checkbox-column, td.checkbox-column {
            width: 40px; /* Adjust this value as needed */
        }

        .button-container {
            display: flex;
            justify-content: flex-end;
            align-items: center;
            gap: 10px;
        }
        .input-group-text {
            display: flex;
            align-items: center;
        }

        <!-- 会话列表样式 -->
        .list-group-item {
            padding: 10px 15px;
            border: 1px solid #ddd;
            border-radius: 5px;
            margin-bottom: 10px;
        }
        .conv-checkbox {
            margin-right: 10px;
        }
        .text-right {
            text-align: right;
        }
        .highlight {
            background-color: #f0f8ff;
        }


        .rag-form-control {
            width: 120px;
            margin-right: 20px;
        }
        .rag-form-check {
            width: 30px;
            margin-right: 0px;
        }
        .rag-form-check-label {
            margin: auto 20px auto 0px;
        }
        #etl-form .form-group {
            margin: 10px;
        }

    </style>
</head>
<body>
<div class="container chat-container">
    <h1 class="mt-5">我的AI助手</h1>
    <ul class="nav nav-tabs" id="myTab" role="tablist">
        <li class="nav-item">
            <a class="nav-link active" id="chat-tab" data-toggle="tab" href="#chat" role="tab" aria-controls="chat" aria-selected="true">Chat UI</a>
        </li>
        <li class="nav-item">
            <a class="nav-link" id="etl-tab" data-toggle="tab" href="#etl" role="tab" aria-controls="etl" aria-selected="false">ETL</a>
        </li>
    </ul>
    <div class="tab-content" id="myTabContent">
        <div class="tab-pane fade show active" id="chat" role="tabpanel" aria-labelledby="chat-tab">
            <div class="row">
                <div class="col-md-3">
                    <div class="card">
                        <div class="card-header">
                            <button class="btn btn-success" id="new-conversation">新建会话</button>
                            <button class="btn btn-danger" id="delete-conversations">删除会话</button>
                        </div>
                        <div class="card-body">
                            <ul id="conversation-list" class="list-group">
                                <!-- Conversation list will be populated here -->
                            </ul>
                        </div>
                    </div>
                </div>
                <div class="col-md-9">
                    <div class="card mt-3 flex-grow-1">
                        <div class="card-body d-flex flex-column">
                            <div id="chat-window" class="chat-window border p-3">
                                <!-- Chat messages will appear here -->
                            </div>
                            <div class="input-group mt-3">
                                <textarea id="user-input" class="form-control" placeholder="请说出你的想法..." rows="3"></textarea>
                            </div>

                            <div class="input-group mt-3 input-group-text">
                                <div class="form-floating mb-3">
                                    <input type="number" id="chat-history-count" class="form-control rag-form-control" min="0" value="100" placeholder="聊天上下数量 [0, +∞]"data-toggle="tooltip" title="聊天上下数量 [0, +∞]">
                                    <label for="chat-history-count">聊天上下数量</label>
                                </div>
                                <div class="form-floating mb-3">
                                    <input type="text" id="send-metadata-type" class="form-control rag-form-control" placeholder="RAG 知识类型（逗号分隔）" data-toggle="tooltip" title="RAG 知识类型（逗号分隔）">
                                    <label for="send-metadata-type">RAG知识类型</label>
                                </div>
                                <div class="form-floating mb-3">
                                    <input type="number" id="rag-topK" class="form-control rag-form-control" min="1" value="10" placeholder="RAG TopK [1, +∞]" data-toggle="tooltip" title="RAG TopK [1, +∞]">
                                    <label for="rag-topK">RAG TopK</label>
                                </div>
                                <div class="form-floating mb-3">
                                    <input type="number" id="rag-similarity-threshold" class="form-control rag-form-control" min="0" max="1" step="0.01" value="0" placeholder="RAG 相似度阈值 [0.0, 1.0]" data-toggle="tooltip" title="RAG 相似度阈值 [0.0, 1.0]">
                                    <label for="rag-similarity-threshold">RAG相似度</label>
                                </div>
<!--                                <div class="form-floating mb-3">-->
<!--                                    <input type="checkbox" id="send-rag-toggle" class="rag-form-check" checked>-->
<!--                                    <label for="send-rag-toggle" class="rag-form-check-label">启用RAG</label>-->
<!--                                </div>-->
                                <input type="checkbox" id="send-rag-toggle" class="rag-form-check" checked>
                                <label for="send-rag-toggle" class="rag-form-check-label">启用RAG</label>
                                <input type="checkbox" id="send-stream-toggle" class="rag-form-check" checked>
                                <label for="send-stream-toggle" class="rag-form-check-label">Stream</label>
                                <div class="button-container">
                                    <button class="btn btn-primary" id="send-chat">发送</button>
                                    <button class="btn btn-danger" id="clear-chat">清空</button>
                                </div>
                            </div>


                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="tab-pane fade" id="etl" role="tabpanel" aria-labelledby="etl-tab">
            <div class="card mt-3">
                <div class="card-body">
                    <form id="etl-form" class="mb-3">
                        <div class="form-row">
                            <div class="form-group col-md-3">
                                <label for="query-id">文档ID</label>
                                <input type="text" id="query-id" class="form-control" placeholder="File ID">
                            </div>
                            <div class="form-group col-md-3">
                                <label for="query-url">文档URL</label>
                                <input type="text" id="query-url" class="form-control" placeholder="URL">
                            </div>
                            <div class="form-group col-md-3">
                                <label for="query-filename">文档名称</label>
                                <input type="text" id="query-filename" class="form-control" placeholder="Filename">
                            </div>
                            <div class="form-group col-md-2">
                                <label for="query-train-status">训练状态</label>
                                <select id="query-train-status" class="form-control">
                                    <option value="">All</option>
                                    <option value="0">未训练</option>
                                    <option value="1">已训练</option>
                                </select>
                            </div>
                        </div>
                        <div class="form-row">
                            <div class="btn-container">
                                <button type="button" class="btn btn-primary" id="search-files">查询</button>
                                <button class="btn btn-danger" id="delete-selected">删除</button>
                                <button class="btn btn-info" id="upload-file">上传文档</button>
                                <button class="btn btn-success" id="train-selected">RAG训练</button>
                            </div>
                        </div>
                    </form>
                    <div class="table-container">
                        <table class="table table-bordered">
                            <thead>
                            <tr>
                                <th class="checkbox-column"><input type="checkbox" id="select-all"></th>
                                <th>文档ID</th>
                                <th>文档名称</th>
                                <th>文档URL</th>
                                <th>知识类型</th>
                                <th>元数据</th>
                                <th>大小</th>
                                <th>平台</th>
                                <th>训练状态</th>
                            </tr>
                            </thead>
                            <tbody id="file-table-body">
                            <!-- Table rows will be inserted here -->
                            </tbody>
                        </table>
                    </div>
                    <nav>
                        <ul class="pagination" id="pagination">
                            <!-- Pagination buttons will be inserted here -->
                        </ul>
                    </nav>
                </div>
            </div>
        </div>
    </div>
</div>

<!-- Upload File Modal -->
<div class="modal fade" id="uploadFileModal" tabindex="-1" role="dialog" aria-labelledby="uploadFileModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="uploadFileModalLabel">上传文档</h5>
<!--                <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">-->
<!--                    <span aria-hidden="true">&times;</span>-->
<!--                </button>-->
            </div>
            <div class="modal-body">
                <form id="upload-file-form">
                    <div class="form-group">
                        <label for="file-input">选择文件</label>
                        <input type="file" id="file-input" class="form-control">
                    </div>
                    <div class="form-group">
                        <label for="metadata-type">知识类型</label>
                        <input type="text" id="metadata-type" class="form-control" placeholder="用半角逗号分隔多个值">
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                <button type="button" class="btn btn-primary" id="submit-upload">上传</button>
            </div>
        </div>
    </div>
</div>

<script>
    //初始化tab页切换逻辑
    document.addEventListener('DOMContentLoaded', function () {
        var triggerTabList = [].slice.call(document.querySelectorAll('#myTab a'))
        triggerTabList.forEach(function (triggerEl) {
            var tabTrigger = new bootstrap.Tab(triggerEl)

            triggerEl.addEventListener('click', function (event) {
                event.preventDefault()
                tabTrigger.show()
            })
        })
    });

    $(document).ready(function() {
        let currentPage = 1;
        const pageSize = 10;

        let currentConversationId = null;

        //初始化提示工具
        $('[data-toggle="tooltip"]').tooltip();


        //查询会话列表
        function fetchConversations(selectFirst = false) {
            $.get('/ai/convs', { pageIndex: 1, pageSize: 10000, orderBy: 'create_time', orderDirection: 'DESC' }, function(data) {
                const conversations = data.records;
                $('#conversation-list').empty();
                conversations.forEach(conv => {
                    $('#conversation-list').append(`
                        <li class="list-group-item" data-id="${conv.id}">
                            <input type="checkbox" class="conv-checkbox" value="${conv.id}">
                            会话 - <b>${conv.id}</b>
                            <div class="text-right">
                                <small class="text-muted">创建时间：${new Date(conv.createTime).toLocaleString()}</small>
                            </div>
                        </li>
                    `);
                });

                if (selectFirst && conversations.length > 0) {
                    // Select the first conversation by default
                    const firstConversation = $('#conversation-list li').first();
                    firstConversation.addClass('highlight');
                    currentConversationId = firstConversation.data('id');
                    fetchChats(currentConversationId);
                }
            });
        }

        //查询会话中的聊天记录
        function fetchChats(conversationId, fromChatId = null) {
            const query = { convId: conversationId, limit: 20 };
            if (fromChatId) query.fromChatId = fromChatId;
            $.get(`/ai/convs/${conversationId}/chats`, query, function(data) {
                for (let i = data.length - 1; i >= 0; i--) {
                    appendMessage(data[i].content, data[i].createdBy === 'user');
                }
            });
        }

        //新建会话
        $('#new-conversation').click(function() {
            $.post('/ai/convs', function(newConversation) {
                fetchConversations();
                // Select the newly created conversation
                setTimeout(() => {
                    const newConvElement = $(`#conversation-list li[data-id="${newConversation.id}"]`);
                    newConvElement.addClass('highlight');
                    currentConversationId = newConversation.id;
                    //fetchChats(currentConversationId);
                }, 100);
            });
        });
        //批量删除会话
        $('#delete-conversations').click(function() {
            const selectedIds = $('.conv-checkbox:checked').map(function() { return $(this).val(); }).get();
            if (selectedIds.length > 0) {
                $.ajax({
                    url: `/ai/convs/${selectedIds.join(',')}`,
                    type: 'DELETE',
                    success: function() {
                        fetchConversations();
                    }
                });
            } else {
                alert('请先选择会话');
            }
        });

        // 初始化会话列表
        $('#conversation-list').on('click', 'li', function() {
            currentConversationId = $(this).data('id');
            $('#chat-window').empty();
            fetchChats(currentConversationId);

            // 移除所有会话的高亮类
            $('#conversation-list li').removeClass('highlight');
            // 为当前点击的会话添加高亮类
            $(this).addClass('highlight');
        });


        //附加聊天记录到界面
        function appendMessage(message, isUser) {
            const messageClass = isUser ? 'user-message' : 'bot-message';
            const icon = isUser ? '👤' : '🤖';
            let mdMessage = marked.parse(message)
            $('#chat-window').append('<div class="' + messageClass + '"><span class="icon">' + icon + '</span><span class="message-content">' + mdMessage + '</span></div>');
            $('#chat-window').scrollTop($('#chat-window')[0].scrollHeight);
        }

        function appendMessageGroup(userMessage) {
            $('#chat-window').append('<div class="message-group"></div>');
            appendMessage(userMessage, true);
        }

        //发送用户的聊天消息
        $('#send-chat').click(function() {
            const userInput = $('#user-input').val();
            const metadataType = $('#send-metadata-type').val();
            const chatHistoryCount = $('#chat-history-count').val();
            const ragTopK = $('#rag-topK').val();
            const ragSimilarityThreshold = $('#rag-similarity-threshold').val();
            let ragFilterExpression = '';

            if (metadataType) {
                const types = metadataType.split(/[,，]/).map(type => `'${type.trim()}'`);
                ragFilterExpression = `type in [${types.join(', ')}]`;
            }

            appendMessageGroup(userInput);
            const isRag = $('#send-rag-toggle').is(':checked');
            const isStream = $('#send-stream-toggle').is(':checked');
            //动态切换是否RAG、Stream
            const url = isRag ? (isStream ? '/ai/chat/rag/stream' : '/ai/chat/rag') : (isStream ? '/ai/chat/stream' : '/ai/chat');
            const requestData = {
                userInput: userInput,
                ragFilterExpression: ragFilterExpression,
                chatConvId: currentConversationId,
                chatHistoryCount: chatHistoryCount,
                ragTopK: ragTopK,
                ragSimilarityThreshold: ragSimilarityThreshold
            };

            if (isStream) {
                //Stream响应处理
                streamBotResponse(url, requestData);
            } else {
                //同步调用响应处理
                $.get(url, requestData, function(response) {
                    appendMessage(response, false);
                });
            }
        });

        //处理大模型返回的聊天响应信息
        function streamBotResponse(url, requestData) {
            let requestUrl = url
                            + '?userInput=' + encodeURIComponent(requestData.userInput)
                            + '&ragFilterExpression=' + encodeURIComponent(requestData.ragFilterExpression)
                            + '&chatConvId=' + encodeURIComponent(requestData.chatConvId)
                            + '&chatHistoryCount=' + requestData.chatHistoryCount
                            + '&ragTopK=' + requestData.ragTopK
                            + '&ragSimilarityThreshold=' + requestData.ragSimilarityThreshold;
            const eventSource = new EventSource(requestUrl);
            let botMessageContainer = $('<div class="bot-message"><span class="icon">🤖</span><span class="message-content"></span></div>');
            $('#chat-window').append(botMessageContainer);
            const messageContent = botMessageContainer.find('.message-content');
            let botMessage = '';
            eventSource.onmessage = function(event) {
                botMessage += event.data;
                messageContent.html(marked.parse(botMessage));
                $('#chat-window').scrollTop($('#chat-window')[0].scrollHeight);
            };

            eventSource.onerror = function() {
                eventSource.close();
            };
        }

        //清空聊天记录
        $('#clear-chat').click(function() {
            $('#chat-window').empty();
        });

        //转换人类可读大小
        function humanReadableSize(size) {
            const i = Math.floor(Math.log(size) / Math.log(1024));
            return (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['B', 'KB', 'MB', 'GB', 'TB'][i];
        }

        //获取训练状态标签
        function getTrainStatusLabel(trainStatus) {
            if (trainStatus === 1) {
                return '<span class="badge bg-success">已训练</span>';
            } else {
                return '<span class="badge bg-warning">未训练</span>';
            }
        }

        //查询并显示文档列表
        function fetchFiles(page) {
            const query = {
                id: $('#query-id').val(),
                url: $('#query-url').val(),
                originalFilename: $('#query-filename').val(),
                trainStatus: $('#query-train-status').val(),
                pageIndex: page,
                pageSize: pageSize
            };

            $.get('/ai/etl/files', query, function(data) {
                const files = data.records;
                const total = data.total;
                const totalPages = Math.ceil(total / pageSize);

                $('#file-table-body').empty();
                files.forEach(file => {
                    const trainStatusLabel = getTrainStatusLabel(file.trainStatus);
                    const fileSize = humanReadableSize(file.size);
                    $('#file-table-body').append(`
                        <tr>
                            <td><input type="checkbox" class="file-checkbox" value="${file.id}"></td>
                            <td>${file.id || ''}</td>
                            <td>${file.originalFilename || ''}</td>
                            <td><a href="${file.url || '#'}" target="_blank">${file.url || ''}</a></td>
                            <td>${file.knowledgeType || ''}</td>
                            <td>${file.metadata || ''}</td>
                            <td>${fileSize || ''}</td>
                            <td>${file.platform || ''}</td>
                            <td>${trainStatusLabel || ''}</td>
                        </tr>
                    `);
                });

                $('#pagination').empty();
                for (let i = 1; i <= totalPages; i++) {
                    $('#pagination').append(`
                        <li class="page-item ${i === page ? 'active' : ''}">
                            <a class="page-link" href="#">${i}</a>
                        </li>
                    `);
                }
            });
        }

        //获取已选中的文件ID列表
        function getSelectedFileIds() {
            const selectedIds = [];
            $('.file-checkbox:checked').each(function() {
                selectedIds.push($(this).val());
            });
            return selectedIds;
        }

        //查询文档分页列表
        $('#search-files').click(function() {
            currentPage = 1;
            fetchFiles(currentPage);
        });

        //文档分页列表处理
        $('#pagination').on('click', '.page-link', function(e) {
            e.preventDefault();
            currentPage = parseInt($(this).text());
            fetchFiles(currentPage);
        });

        //文档全选处理
        $('#select-all').change(function() {
            $('.file-checkbox').prop('checked', $(this).prop('checked'));
        });

        //批量删除已选中的文档
        $('#delete-selected').click(function(e) {
            e.preventDefault();
            const selectedIds = getSelectedFileIds();
            if (selectedIds.length > 0) {
                $.ajax({
                    url: `/ai/etl/files/${selectedIds.join(',')}`,
                    type: 'DELETE',
                    success: function() {
                        fetchFiles(currentPage);
                    }
                });
            } else {
                alert('请先选择文档');
            }
        });

        //批量训练已选中的文档
        $('#train-selected').click(function(e) {
            e.preventDefault();
            const selectedIds = getSelectedFileIds();
            if (selectedIds.length > 0) {
                // Show waiting background
                $('body').append('<div id="waiting-background" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); z-index: 9999; display: flex; justify-content: center; align-items: center; color: white; font-size: 24px;">Training...</div>');

                $.post(`/ai/etl/train/${selectedIds.join(',')}`, function() {
                    // Remove waiting background
                    $('#waiting-background').remove();
                    fetchFiles(currentPage);
                }).fail(function() {
                    // Remove waiting background
                    $('#waiting-background').remove();
                    alert('文档训练失败，请重试');
                });
            } else {
                alert('请先选择文档');
            }
        });

        //上传文档输入处理
        $('#upload-file').click(function(e) {
            e.preventDefault();
            $('#file-input').val('');
            $('#metadata-type').val('');
            $('#uploadFileModal').modal('show');
        });
        //提交上传文档
        $('#submit-upload').click(function() {
            const file = $('#file-input')[0].files[0];
            const metadataType = $('#metadata-type').val();
            if (file) {
                const formData = new FormData();
                formData.append('file', file);
                formData.append('type', metadataType);

                // Show waiting background
                $('body').append('<div id="waiting-background" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); z-index: 9999; display: flex; justify-content: center; align-items: center; color: white; font-size: 24px;">Uploading...</div>');

                $.ajax({
                    url: '/ai/etl/files/upload',
                    type: 'POST',
                    data: formData,
                    processData: false,
                    contentType: false,
                    success: function() {
                        // Remove waiting background
                        $('#waiting-background').remove();
                        $('#uploadFileModal').modal('hide');
                        // Refresh table data
                        fetchFiles(currentPage);
                    },
                    error: function() {
                        // Remove waiting background
                        $('#waiting-background').remove();
                        alert('文件上传失败');
                    }
                });
            }
        });

        //初始化查询会话列表
        fetchConversations(true);

        //初始查询文档列表
        fetchFiles(currentPage);
    });
</script>
<script th:src="@{/webjars/bootstrap/5.3.3/js/bootstrap.min.js}"></script>
</body>
</html>